home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 November: Tool Chest / Dev.CD Nov 98 TC.toast / Sample Code / Snippets / Networking / ATP Demo 1.0 / Atalk.c next >
Encoding:
C/C++ Source or Header  |  1994-10-28  |  17.1 KB  |  644 lines  |  [TEXT/MPS ]

  1. /*****************************************************************
  2.  
  3.     Program:    < ATP Demo >
  4.     File:        < Atalk.c >
  5.     
  6.     Written by  Scott Kuechle
  7.     of <Apple Macintosh Developer Technical Support>
  8.     
  9.     10/92 SRK created
  10.     8/94 SRK Modified to use a queue of parameter
  11.              blocks.
  12.  
  13.     Copyright © 1992, 1994 Apple Computer, Inc.
  14.     All rights reserved.
  15.     
  16. *****************************************************************/
  17.  
  18. /*****************************************************************/
  19. /*  I N C L U D E S
  20. /*****************************************************************/
  21.  
  22. #include    "ATP Demo.h"
  23. #include    "ATP Demo.protos"
  24.  
  25.  
  26. /********************************************************************
  27. /*  G L O B A L   V A R I A B L E   D E C L A R A T I O N S
  28. /********************************************************************/
  29.  
  30.  
  31. ATPPBPtr        gATPPBPtr;            /* the parameter block for GetZoneList call */
  32. XPPParmBlkPtr    gXPBPBPtr;            /* structure for Phase 2 NBP lookups */
  33. short            xppDriverRefNum;
  34. Str255             gZoneString, gObjStr, gTypeStr;
  35. Str32             myName;
  36. short             gMenuItem;
  37. NamesTableEntry myNTE;
  38. AddrBlock         theBridgeAddress;
  39.  
  40. /*****************************************************************/
  41. /*
  42. /* E X T E R N A L S
  43. /*
  44. /*****************************************************************/
  45.  
  46. extern SysEnvRec    gMac;                /* set up by Initialize */
  47.  
  48. extern void         ShowError(short index);
  49. extern void         CopyPstr(Ptr pSource, Ptr pDest);
  50. extern void         Terminate();
  51. extern void            Exit(short message);
  52. extern qsort (Ptr base, long n, long size, ProcPtr compare);
  53.  
  54.  
  55.  
  56. #pragma segment Main
  57.  
  58. //#pragma segment atlk
  59. // *****************************************************************
  60. // *    registerMyName
  61. // *
  62. // *    registers our nbp name on the network so we can find other
  63. // *    machines that are running our application.
  64. // *****************************************************************
  65. void registerMyName(char socket)
  66. {
  67.     MPPParamBlock pb;
  68.     StringHandle userName;
  69.     
  70.  
  71.         userName = GetString(-16096);
  72.  
  73.         myName[0] = 0;
  74.         if (userName != nil)
  75.         {
  76.             if (*userName[0] != 0)
  77.                 BlockMove(*userName,&myName,*userName[0]+1);
  78.         }
  79.  
  80.         NBPSetNTE((Ptr)&myNTE, &myName, atpEntityFilter, "\p*", socket);
  81.     
  82.         pb.NBP.interval = 2;
  83.         pb.NBP.count = 3;
  84.         pb.NBP.NBPPtrs.entityPtr = (Ptr)&myNTE;
  85.         pb.NBP.parm.verifyFlag = 1;
  86.         if (PRegisterName(&pb,false) != noErr)
  87.             ShowError(nbpErr);
  88.     
  89. }
  90.  
  91. // *****************************************************************
  92. // *    removeMyName
  93. // *
  94. // *    removes our nbp name from the network.
  95. // *****************************************************************
  96. void removeMyName()
  97. {
  98.     MPPParamBlock pb;
  99.     OSErr err;
  100.  
  101.         pb.NBP.NBPPtrs.entityPtr = (Ptr)&myNTE.nt.entityData;
  102.         
  103.         err = PRemoveName(&pb, false);
  104. }
  105.  
  106.  
  107.  
  108. // *****************************************************************
  109. // *    myCompare
  110. // *
  111. // *    this uses stand International Utilites package for sorting
  112. // *****************************************************************
  113. long myCompare (Str255 aStr, Str255 bStr)
  114.     {
  115.         return ((long)IUCompString(bStr, aStr));
  116.     }
  117.  
  118.  
  119. // *****************************************************************
  120. // *    letsSort
  121. // *
  122. // * calls a standard C qSort routine compiled with Pascal calling 
  123. // * conventions the 33 is the standard size of a Str32 type, which
  124. // * is the standard size of an AppleTalk NBP object.
  125. // *****************************************************************
  126. void letsSort (Ptr theBuffPtr, long numZonesGot)
  127.     {
  128.         qsort(theBuffPtr, numZonesGot, 33, &myCompare);
  129.     }
  130.  
  131.  
  132. // *****************************************************************
  133. // *    addZonesToBuffer
  134. // *
  135. // *    
  136. // *****************************************************************
  137. void addZonesToBuffer (Ptr LkUpBuffer,
  138.                 Ptr BufferForZoneMenu,
  139.                 short NumZonesGot,
  140.                 short CurrentTotal)
  141. {    
  142.     char curLength;
  143.     long index;
  144.     short i;
  145.  
  146.         index = 0;
  147.         curLength = 0;
  148.         for (i=CurrentTotal;i<=(NumZonesGot + CurrentTotal) && (i < maxZones);++i)
  149.         {
  150.             curLength = *(LkUpBuffer + index);
  151.             BlockMove((LkUpBuffer + index), (BufferForZoneMenu + (i * 33)), 33);
  152.             index = index + curLength + 1;
  153.         }
  154. }
  155.  
  156. // *****************************************************************
  157. // *    parseItemsAddToMenu
  158. // *
  159. // *    this routine adds zone name items to our zones popup menu
  160. // *****************************************************************
  161. void parseItemsAddToMenu (Ptr theBuffPtr,
  162.                     MenuHandle zoneMenu,
  163.                     short NumZonesGot)
  164. {    
  165.     long index;
  166.     Str255 tempString;
  167.     short i;
  168.  
  169.         letsSort(theBuffPtr, NumZonesGot);
  170.     
  171.         index = 0;
  172.         for (i=0; i<=(NumZonesGot - 1); ++i)
  173.             {
  174.                 BlockMove((theBuffPtr + i * 33), &tempString, 33);
  175.                     /* initially insert a blank item so meta-characters aren't used */
  176.                 AppendMenu(zoneMenu, "\p ");
  177.                     /* use SetItem so we can display meta-chars in zone names */
  178.                 SetItem(zoneMenu, i + 1, tempString);
  179.     
  180.             }
  181. }
  182.  
  183. // *****************************************************************
  184. // *    zonesPresent
  185. // *
  186. // * this checks to see if there is a local bridge available
  187. // *****************************************************************
  188. Boolean zonesPresent()
  189. {    
  190.     short mynode, ignore;
  191.  
  192.  
  193.         theBridgeAddress.aNode = 0;
  194.     
  195.         theBridgeAddress.aNode = GetBridgeAddress();
  196.         ignore = GetNodeAddress(&mynode, &theBridgeAddress.aNet);
  197.     
  198.         if (theBridgeAddress.aNode != 0) 
  199.         {
  200.             theBridgeAddress.aSocket = theBridgeSocket;
  201.             return true;
  202.         }
  203.         else
  204.         {
  205.             CopyPstr("\p*", &gZoneString);
  206.             return false;
  207.         }
  208. }
  209.  
  210.  
  211. // *****************************************************************
  212. // *    parseLkupBuffAddToMenu
  213. // *
  214. // *    this routine takes all the names returned from the nbp lookup
  215. // *    and checks to see if the item is already in the list. If not,
  216. // *    the item is added to the appropriate popup menu.
  217. // *****************************************************************
  218. void parseLkupBuffAddToMenu (Ptr theBuffPtr,
  219.                         Ptr bigBuffer,
  220.                         MenuHandle lookupMenu,
  221.                         short NumGot,
  222.                         Boolean doObjects)
  223. {    
  224.     Str255 menuString, str;
  225.     short i, j, k;
  226.     EntityName abEntity;
  227.     AddrBlock address;
  228.     OSErr resultCode;
  229.     Boolean weHaveDupe;
  230.  
  231.         k = 1;
  232.         for (i=1; i<=NumGot; ++i)
  233.         {
  234.             resultCode = NBPExtract(theBuffPtr, NumGot, i, &abEntity, &address);
  235.             
  236.             if (doObjects)
  237.                 BlockMove(&abEntity.objStr,&menuString,abEntity.objStr[0]+1);
  238.             else    /* do type strings */
  239.                 BlockMove(&abEntity.typeStr,&menuString,abEntity.typeStr[0]+1);
  240.  
  241.             weHaveDupe = false;
  242.             j = 0;
  243.             do
  244.             {
  245.                 j = j + 1;
  246.                 BlockMove((bigBuffer + (j - 1) * 33), &str, 33);
  247.                 if (EqualString(str, menuString, false, true))
  248.                     weHaveDupe = true;
  249.             }
  250.             while ((j <= k) && (weHaveDupe == false));
  251.  
  252.             if (weHaveDupe == false) 
  253.             {
  254.                 BlockMove(&menuString, (bigBuffer + (k - 1) * 33), 33);
  255.                 k = k + 1;
  256.             }
  257.         }
  258.         parseItemsAddToMenu(bigBuffer, lookupMenu, k - 1);
  259. }
  260.  
  261.  
  262. // *****************************************************************
  263. // *    LookupNames
  264. // *
  265. // *    issues an nbp lookup for the desired object, type and zone
  266. // *    the user has specified with the target machine popup menus.
  267. // *****************************************************************
  268. void LookupNames (MenuHandle lookupMenu,
  269.                 Boolean doObjects)
  270. {    
  271.     Str32 NBPObject, NBPType, NBPZone;
  272.     NamesTableEntry lookupEntity;
  273.     Ptr buffer; /* totally gross mondo buffer for returned zones */
  274.     Ptr bigBuffer;
  275.     MPPParamBlock pbLKP;
  276.  
  277.         buffer = nil;
  278.         bigBuffer = nil;
  279.         
  280.         buffer = NewPtr(BigLookupBuffer);
  281.         if (buffer == nil)
  282.             return;
  283.  
  284.         bigBuffer = NewPtr(250 * 33);
  285.         if (bigBuffer == nil)
  286.             goto Exit;
  287.  
  288.         CopyPstr("\p=", NBPObject);
  289.  
  290.         if (!doObjects)
  291.             CopyPstr("\p=", NBPType);
  292.         else
  293.             BlockMove(&gTypeStr,&NBPType,gTypeStr[0]+1);
  294.  
  295.         if (zonesPresent()) 
  296.             BlockMove(&gZoneString,&NBPZone,gZoneString[0]+1);
  297.         else
  298.             CopyPstr("\p*", NBPZone);
  299.  
  300.         NBPSetEntity((Ptr)&lookupEntity.nt.entityData, NBPObject, NBPType, NBPZone);
  301.  
  302.         pbLKP.NBP.ioCompletion = nil;
  303.         pbLKP.NBP.interval = 3;
  304.         pbLKP.NBP.count = 3;
  305.         pbLKP.NBPentityPtr = &lookupEntity.nt.entityData;
  306.         pbLKP.NBPretBuffSize = BigLookupBuffer;
  307.         pbLKP.NBPretBuffPtr = buffer;
  308.         pbLKP.NBPmaxToGet = (BigLookupBuffer/sizeof(NTElement));
  309.  
  310.         if (PLookupName(&pbLKP, false) == noErr)
  311.             if (pbLKP.NBPnumGotten > 0)
  312.                 parseLkupBuffAddToMenu(buffer, bigBuffer, lookupMenu, pbLKP.NBPnumGotten, doObjects);
  313.  
  314. Exit:
  315.         if (buffer != nil)
  316.             DisposPtr(buffer);
  317.             
  318.         if (bigBuffer != nil)
  319.             DisposPtr(bigBuffer);
  320.  
  321. }
  322.  
  323. // *****************************************************************
  324. // *    BuildZoneListPhase1
  325. // *
  326. // *    Create the list of zones on the network. Find a bridge to talk to , if one is
  327. // *     present, then ask it for zone names. Add the names to the list in the dialog.
  328. // *****************************************************************
  329. void BuildZoneListPhase1(MenuHandle zoneMenu)
  330. {
  331.     BDSElement    dBDS;                /* the BDS for GetZoneList call */
  332.     ATPPBPtr    gATPPBPtr;
  333.     Ptr            gZones,sortBuffer;
  334.     long        tempUserData;
  335.     short        zIndex,zoneCallType;
  336.     Boolean        DontGetMoreZones;
  337.     short        NumZonesGot, totalZones;
  338.     
  339.  
  340.         
  341.         gATPPBPtr = nil;                                            /* init some important variables*/
  342.         gZones = nil;
  343.         sortBuffer = nil;
  344.     
  345.         if (zonesPresent() == false)
  346.             return;
  347.     
  348.         gATPPBPtr = (ATPPBPtr)NewPtr(sizeof(ATPParamBlock));
  349.         if (gATPPBPtr == nil)
  350.             goto Exit;
  351.             
  352.         gZones = NewPtr(kZonesSize);
  353.         if (gZones == nil)
  354.             goto Exit;
  355.             
  356.         sortBuffer = NewPtr(ZoneBufSize);
  357.         if (sortBuffer == nil)
  358.             goto Exit;
  359.  
  360.         zoneCallType = kGetZoneList;
  361.         zIndex = 1;
  362.             
  363.         dBDS.buffSize = kZonesSize;                                    /* set up BDS */
  364.         dBDS.buffPtr = gZones;
  365.         dBDS.dataSize = 0;
  366.         dBDS.userBytes = 0;
  367.     
  368.         gATPPBPtr->ATPatpFlags = 0;
  369.  
  370.     
  371.         gATPPBPtr->ATPaddrBlock.aNet = theBridgeAddress.aNet;
  372.         gATPPBPtr->ATPaddrBlock.aNode = theBridgeAddress.aNode;                    /* get node of bridge */
  373.         gATPPBPtr->ATPaddrBlock.aSocket = kZIPSocket;                /* the socket we want */
  374.         gATPPBPtr->ATPreqLength = 0;
  375.         gATPPBPtr->ATPreqPointer = nil;
  376.         gATPPBPtr->ATPbdsPointer = (Ptr) &dBDS;
  377.         gATPPBPtr->ATPnumOfBuffs = 1;
  378.         gATPPBPtr->ATPtimeOutVal = kATPTimeOutVal;
  379.         gATPPBPtr->ATPretryCount = kATPRetryCount;
  380.     
  381.         NumZonesGot = 0;
  382.         totalZones = 0;
  383.         DontGetMoreZones = false;
  384.     
  385.             /*     keep going until none left (and we haven't exceeded our buffer size) */
  386.         while (!DontGetMoreZones && (totalZones <= maxZones)) 
  387.         {
  388.             zIndex += NumZonesGot;            /* index count. 1 for start */
  389.  
  390.             BlockMove((Ptr) &zoneCallType + 1, (Ptr) &tempUserData, 1L);
  391.             BlockMove((Ptr) &zIndex, (Ptr)&tempUserData + 2, 2L);
  392.  
  393.             gATPPBPtr->ATPuserData = tempUserData;                        /* indicate GetZoneList request */
  394.             
  395.             if (PSendRequest(gATPPBPtr, false) != noErr)        /* send sync request */
  396.                 Exit(DrvrErr);
  397.             
  398.             tempUserData = dBDS.userBytes;
  399.             BlockMove((Ptr) &tempUserData, (Ptr) &DontGetMoreZones, 1); /* the highbyte will be nonzero if its the last packet of zones */
  400.             BlockMove((Ptr)&tempUserData + 2, (Ptr) &NumZonesGot, 2);
  401.     
  402.             addZonesToBuffer(dBDS.buffPtr,sortBuffer,NumZonesGot,totalZones);            
  403.  
  404.             totalZones += NumZonesGot;
  405.         }
  406.  
  407.         totalZones = (totalZones <= maxZones) ? totalZones : maxZones;
  408.         parseItemsAddToMenu(sortBuffer,zoneMenu,totalZones);
  409.  
  410.         Exit:
  411.             if (gATPPBPtr != nil)
  412.                 DisposePtr((Ptr)gATPPBPtr);
  413.             if (gZones != nil)
  414.                 DisposePtr(gZones);
  415.             if (sortBuffer != nil)
  416.                 DisposePtr(sortBuffer);
  417.  
  418. } /* BuildZoneList */
  419.  
  420. // *****************************************************************
  421. // *    BuildZoneListPhase2
  422. // *
  423. // *    Create the list of zones on the network. Find a bridge to talk to , if one is
  424. // *     present, then ask it for zone names. Add the names to the list in the dialog.
  425. // *****************************************************************
  426. void BuildZoneListPhase2(MenuHandle zoneMenu)
  427. {
  428.     Ptr            bigBuffer;
  429.     short        TotalZones;
  430.     Ptr            gZones;     /* the data buffer for GetZoneList call */
  431.  
  432.  
  433.         gXPBPBPtr = nil;                                            /* init some important variables*/
  434.         gZones = nil;
  435.         bigBuffer = nil;
  436.     
  437.     
  438.         if (zonesPresent() == false)
  439.             return;
  440.     
  441.         gXPBPBPtr = (XPPParmBlkPtr)NewPtr(sizeof(XCallParam));
  442.         if (gXPBPBPtr == nil)
  443.             return;
  444.         
  445.         gZones = NewPtr(kZonesSize);
  446.         if (gZones == nil)
  447.             goto Exit;
  448.     
  449.             /* big, ugly mondo buffer to hold complete zone list so we can sort them */
  450.         bigBuffer = NewPtr(ZoneBufSize);
  451.         if (bigBuffer == nil)
  452.             goto Exit;
  453.     
  454.         gXPBPBPtr->XCALL.zipInfoField[0] = 0;    /* ALWAYS 0 on first call.  has state info on subsequent calls */
  455.         gXPBPBPtr->XCALL.zipInfoField[1] = 0;    /* ALWAYS 0 on first call.  has state info on subsequent calls */
  456.         gXPBPBPtr->XCALL.zipLastFlag = 0;
  457.     
  458.         gXPBPBPtr->XCALL.ioRefNum = xppDriverRefNum;
  459.         gXPBPBPtr->XCALL.csCode = xCall;
  460.         gXPBPBPtr->XCALL.xppSubCode = zipGetZoneList;
  461.         gXPBPBPtr->XCALL.xppTimeout = kATPTimeOutVal;
  462.         gXPBPBPtr->XCALL.xppRetry = kATPRetryCount;
  463.         gXPBPBPtr->XCALL.zipBuffPtr = (Ptr) gZones;
  464.     
  465.         TotalZones = 0;
  466.     
  467.         do
  468.         {
  469.             if (PBControl((ParmBlkPtr) gXPBPBPtr, false) != noErr)
  470.                 Exit(DrvrErr);
  471.  
  472.             addZonesToBuffer(gZones,bigBuffer,gXPBPBPtr->XCALL.zipNumZones,TotalZones);
  473.             TotalZones = TotalZones + gXPBPBPtr->XCALL.zipNumZones;                        /* find out how many returned */
  474.     
  475.         } while ((gXPBPBPtr->XCALL.zipLastFlag == 0) && (TotalZones <= maxZones));                /*     keep going until none left */
  476.         
  477.         TotalZones = (TotalZones <= maxZones) ? TotalZones : maxZones;
  478.         parseItemsAddToMenu(bigBuffer,zoneMenu,TotalZones);
  479.     
  480.     Exit:
  481.     
  482.         if (gXPBPBPtr != nil)
  483.             DisposPtr((Ptr)gXPBPBPtr);            /* get rid of pb block */
  484.     
  485.         if (gZones != nil)
  486.             DisposPtr(gZones);                    /* and buffer */
  487.     
  488.         if (bigBuffer != nil)
  489.             DisposPtr(bigBuffer);                    /* and buffer */
  490.  
  491. } /* BuildZoneList */
  492.  
  493.  
  494. // *****************************************************************
  495. // *    GetZones
  496. // *
  497. // *    checks which version of AppleTalk we are using and then calls
  498. // *     the appropriate routine for building the zone list.
  499. // *****************************************************************
  500. void GetZones(MenuHandle ZoneMenu)
  501. {
  502.     if(gMac.atDrvrVersNum > 52)
  503.         BuildZoneListPhase2(ZoneMenu);                                    /*    put the stuff into the list */
  504.     else
  505.         BuildZoneListPhase1(ZoneMenu);                                    /*    put the stuff into the list */
  506. }
  507.  
  508.  
  509. //#pragma segment Initialize
  510. // *****************************************************************
  511. // *    getOurZonePhase2
  512. // *
  513. // *    gets our local zone using AppleTalk Phase 2 calls
  514. // *****************************************************************
  515. void getOurZonePhase2()
  516. {
  517.  
  518.     gXPBPBPtr = nil;            /* init some important variables*/
  519.     gZoneString[0] = 0;
  520.  
  521.  
  522.     if (zonesPresent() == false)
  523.         return;
  524.     
  525.     gXPBPBPtr = (XPPParmBlkPtr)NewPtr(sizeof(XCallParam));
  526.     if (gXPBPBPtr == nil)
  527.         return;
  528.  
  529.     gXPBPBPtr->XCALL.zipInfoField[0] = 0;    /* ALWAYS 0 on first call.  has state info on subsequent calls */
  530.     gXPBPBPtr->XCALL.zipInfoField[1] = 0;    /* ALWAYS 0 on first call.  has state info on subsequent calls */
  531.     gXPBPBPtr->XCALL.zipLastFlag = 0;
  532.  
  533.     gXPBPBPtr->XCALL.ioRefNum = xppDriverRefNum;
  534.     gXPBPBPtr->XCALL.csCode = xCall;
  535.     gXPBPBPtr->XCALL.xppSubCode = zipGetMyZone;
  536.     gXPBPBPtr->XCALL.xppTimeout = kATPTimeOutVal;
  537.     gXPBPBPtr->XCALL.xppRetry = kATPRetryCount;
  538.     gXPBPBPtr->XCALL.zipBuffPtr = (Ptr)&gZoneString;
  539.  
  540.     if (PBControl((ParmBlkPtr) gXPBPBPtr, false) != noErr)        /* send sync control call */
  541.         Exit(DrvrErr);
  542.  
  543.     if (gXPBPBPtr != nil)
  544.         DisposPtr((Ptr)gXPBPBPtr);            /* get rid of pb block */
  545.     
  546. }
  547.  
  548.  
  549. // *****************************************************************
  550. // *    getOurZonePhase1
  551. // *
  552. // *    gets our local zone using AppleTalk Phase 1 calls
  553. // *****************************************************************
  554. void getOurZonePhase1()
  555. {    
  556.     BDSElement myZoneBDS;
  557.     ATPParamBlock ZonePB;
  558.     long tempUserData;
  559.     Ptr theBufferPtr;
  560.     char zoneCallType;
  561.  
  562.         zoneCallType = 7;  /*8 for zone list   7 returns my zone */
  563.         theBufferPtr = nil;
  564.         gZoneString[0] = 0;
  565.  
  566.         
  567.         if (zonesPresent() == true)
  568.         {
  569.             theBufferPtr = NewPtr(33);
  570.             if (theBufferPtr != nil) 
  571.             {
  572.                 myZoneBDS.buffSize = 33;
  573.                 myZoneBDS.buffPtr = theBufferPtr;
  574.                 myZoneBDS.dataSize = 0;
  575.                 myZoneBDS.userBytes = 0;
  576.  
  577.                 ZonePB.ATP.atpFlags = 0;
  578.                 ZonePB.ATP.ioCompletion = nil;
  579.  
  580.                 ZonePB.ATP.userData = 0;/*  ATP user data  */
  581.                 ZonePB.ATP.addrBlock = theBridgeAddress;
  582.                 ZonePB.ATP.reqLength = 0;
  583.                 ZonePB.ATP.reqPointer = nil;
  584.                 ZonePB.ATP.bdsPointer = (Ptr)&myZoneBDS;
  585.                 ZonePB.ATPnumOfBuffs = 1;
  586.                 ZonePB.ATPtimeOutVal = 2;
  587.                 ZonePB.ATPretryCount = 3;
  588.  
  589.                 /* 0 this out so bottom three bytes are 0 */
  590.                 tempUserData = 0;
  591.                 BlockMove(&zoneCallType, (Ptr)&tempUserData, 1);
  592.  
  593.                 ZonePB.ATP.userData = tempUserData;
  594.  
  595.                 gZoneString[0] = 0;
  596.                 if (PSendRequest(&ZonePB, false) == noErr) 
  597.                 {
  598.                     BlockMove(myZoneBDS.buffPtr, &gZoneString, 33);
  599.                 }
  600.                 DisposPtr(theBufferPtr);
  601.             }
  602.         }
  603. }
  604.  
  605. // *****************************************************************
  606. // *    InitAppleTalk
  607. // *
  608. // *    opens the appropriate AppleTalk drivers
  609. // *****************************************************************
  610. OSErr InitAppleTalk()
  611. {
  612.     OSErr err;
  613.     short ref;
  614.     
  615.         if (gMac.atDrvrVersNum > 52)
  616.         {
  617.             err = OpenDriver("\p.MPP",&ref);
  618.             if (err != noErr)
  619.                 return err;
  620.     
  621.             err = OpenDriver("\p.XPP",&xppDriverRefNum);
  622.         }
  623.         else
  624.             err = MPPOpen();
  625.     
  626.         return err;
  627.     
  628. }
  629.  
  630. // *****************************************************************
  631. // *    GetOurZone
  632. // *
  633. // *    checks which version of AppleTalk we are using and then calls
  634. // *    the appropriate phase 1 or phase 2 call to get the local zone.
  635. // *****************************************************************
  636. void GetOurZone()
  637. {
  638.     if(gMac.atDrvrVersNum > 52)
  639.         getOurZonePhase2();                                    /*    put the stuff into the list */
  640.     else
  641.         getOurZonePhase1();                                    /*    put the stuff into the list */
  642.  
  643. }
  644.